package com.zxy.allSearcher.manager;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxy.allSearcher.common.ErrorCode;
import com.zxy.allSearcher.constant.CommonConstant;
import com.zxy.allSearcher.datasource.DataSource;
import com.zxy.allSearcher.datasource.DataSourceRegistry;
import com.zxy.allSearcher.exception.BusinessException;
import com.zxy.allSearcher.model.dto.post.PostQueryRequest;
import com.zxy.allSearcher.model.dto.search.SearchTextRequest;
import com.zxy.allSearcher.model.dto.user.UserQueryRequest;
import com.zxy.allSearcher.model.entity.Picture;
import com.zxy.allSearcher.model.enums.SearchTypeEnum;
import com.zxy.allSearcher.model.vo.PostVO;
import com.zxy.allSearcher.model.vo.SearchVO;
import com.zxy.allSearcher.model.vo.UserVO;
import com.zxy.allSearcher.service.PictureService;
import com.zxy.allSearcher.service.PostService;
import com.zxy.allSearcher.service.UserService;
import com.zxy.allSearcher.utils.PageUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * 搜索外观
 *
 * @author zxy
 * @since 2023/9/16
 **/
@Component
public class SearchFacade {
    @Resource
    private PictureService pictureService;
    @Resource
    private UserService userService;
    @Resource
    private PostService postService;
    @Resource
    private DataSourceRegistry dataSourceRegistry;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    /*
    @Resource
    private AllDataSource allDataSource;  // 优化的聚合搜索数据源*/

    /**
     * 分页获取列表（封装类）
     * 实时获取数据形态，建议添加全部字段默认为空，知识所有数据
     */
    public SearchVO searchAll(SearchTextRequest searchTextRequest, HttpServletRequest request) {
        // 请求参数判断
        String type = searchTextRequest.getType();
        SearchTypeEnum searchTypeEnum = SearchTypeEnum.getEnumByValue(type);
        if (StringUtils.isBlank(type) || searchTypeEnum == null) {
            // All也是一种标签，没有这种类型（type = null）本身就是一种错误
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 检索词+分页信息+查询结果集
        String searchText = searchTextRequest.getSearchText();
        long current = searchTextRequest.getCurrent();
        long size = searchTextRequest.getPageSize();
        PageUtils.validPage(current, size);

        SearchVO searchVO = new SearchVO();
        // 异步查询
        if (searchTypeEnum == SearchTypeEnum.ALL) {
            // 聊胜于无的优化，实在是爬不动图片啊。。。
            // searchVO = allDataSource.doSearch(searchText, current, size);

            // 任务异步执行
            CompletableFuture<Page<UserVO>> tk1 = CompletableFuture.supplyAsync(() -> {
                UserQueryRequest userQueryRequest = new UserQueryRequest();
                userQueryRequest.setUserName(searchText);
                return userService.listUserVOByPage(userQueryRequest);
            });
            CompletableFuture<Page<PostVO>> tk2 = CompletableFuture.supplyAsync(() -> {
                PostQueryRequest postQueryRequest = new PostQueryRequest();
                postQueryRequest.setSearchText(searchText);
                return postService.listPostVOByPage(postQueryRequest, request);
            });
            CompletableFuture<Page<Picture>> tk3 = CompletableFuture.supplyAsync(() ->
                    pictureService.searchPicture(searchText, 1, 10));

            // 好像不需要一起返回。。。数据间并无依赖，只不过是一起返回
            // CompletableFuture.allOf(tk1, tk2, tk3);

            Page<UserVO> userVOPage;
            Page<PostVO> postVOPage;
            Page<Picture> picturePage;
            try {
                userVOPage = tk1.get();
                postVOPage = tk2.get();
                picturePage = tk3.get();
            } catch (Exception e) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "聚合搜索获取数据有误");
            }

            // 3、封装返回结果
            searchVO.setPostList(postVOPage.getRecords());
            searchVO.setUserList(userVOPage.getRecords());
            searchVO.setPictureList(picturePage.getRecords());

        } else {
            DataSource<?> dataSource = dataSourceRegistry.getDataSourceByType(type);
            Page<?> data = dataSource.doSearch(searchText, current, size);
            searchVO.setDataList(data.getRecords());
        }
        // 记录热词
        statisticsSearch(searchText);
        return searchVO;
    }

    /**
     * 添加热词（top 10）
     *
     * @param search
     */
    public void statisticsSearch(String search) {
        Long size = stringRedisTemplate.opsForHash().size(CommonConstant.HOT_KEY);
        // 到10，排除最小的热词
        if (size >= 10) {
            Map<Object, Object> searches = stringRedisTemplate.opsForHash().entries(CommonConstant.HOT_KEY);
            Integer min = Integer.MAX_VALUE;
            Integer tem;
            String minKey = "";
            for (Map.Entry<Object,Object> s : searches.entrySet()){
                tem = (Integer) s.getValue();
                if(tem < min){
                    min = tem;
                    minKey = String.valueOf(s.getKey());
                }
            }
            stringRedisTemplate.opsForHash().delete(CommonConstant.HOT_KEY,minKey);
        }
        // 不足10，补充到10/检索次数+1
        Object o = stringRedisTemplate.opsForHash().get(CommonConstant.HOT_KEY, search);
        if (o == null) {
            stringRedisTemplate.opsForHash().put(CommonConstant.HOT_KEY, search, "1");
        }else {
            stringRedisTemplate.opsForHash().increment(CommonConstant.HOT_KEY, search,1);
        }
    }
}
